/*
 *  Copyright (C) 2011  social-tourist.org
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

package org.socialtourist.web.server;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.jdo.PersistenceManager;
import javax.jdo.Query;

import java.util.Properties;

import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.AddressException;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import org.socialtourist.web.client.SocialTouristService;
import org.socialtourist.web.shared.FieldVerifier;
import org.socialtourist.web.shared.SocialTouristException;
import org.socialtourist.web.shared.data.Image;
import org.socialtourist.web.shared.data.Need;
import org.socialtourist.web.shared.data.SocialProject;

import com.google.gwt.user.server.rpc.RemoteServiceServlet;

/**
 * The server side implementation of the RPC service. GWT example.
 */
@SuppressWarnings("serial")
public class SocialTouristServiceImpl extends RemoteServiceServlet implements
		SocialTouristService {

	private static final Logger log = Logger
			.getLogger(SocialTouristServiceImpl.class.getName());
	private static final String REGISTERED_USER = "logged_in_user";

	public String greetServer(String input) throws IllegalArgumentException {
		// Verify that the input is valid.
		if (!FieldVerifier.isValidName(input)) {
			// If the input is not valid, throw an IllegalArgumentException back
			// to
			// the client.
			throw new IllegalArgumentException(
					"Name must be at least 4 characters long");
		}

		String serverInfo = getServletContext().getServerInfo();
		String userAgent = getThreadLocalRequest().getHeader("User-Agent");

		// Escape data from the client to avoid cross-site script
		// vulnerabilities.
		input = escapeHtml(input);
		userAgent = escapeHtml(userAgent);

		return "Hello, " + input + "!<br><br>I am running " + serverInfo
				+ ".<br><br>It looks like you are using:<br>" + userAgent;
	}

	/**
	 * Escape an html string. Escaping data received from the client helps to
	 * prevent cross-site script vulnerabilities.
	 * 
	 * @param html
	 *            the html string to escape
	 * @return the escaped string
	 */
	private String escapeHtml(String html) {
		if (html == null) {
			return null;
		}
		return html.replaceAll("&", "&amp;").replaceAll("<", "&lt;")
				.replaceAll(">", "&gt;");
	}

	@Override
	public List<SocialProject> getProjects() {
		testEmpty();

		List<SocialProject> result = queryAllProjects();
		return result;
	}

	private List<SocialProject> queryAllProjects() {
		PersistenceManager pm = PMF.get().getPersistenceManager();
		Query query = pm.newQuery(SocialProject.class);
		query.setFilter("isActive == activeParam");
		query.declareParameters("Boolean activeParam");
		
		try {

			List<SocialProject> queryRes = (List<SocialProject>) query
					.execute(Boolean.TRUE);
			List<SocialProject> results = new ArrayList<SocialProject>();

			// Recreate instances because JDO object have issues being
			// serialized to GWT client.
			for (SocialProject project : queryRes) {
				Need[] needs = new Need[project.getNeeds().size()];
				for (int i = 0; i < needs.length; i++) {
					Need need = project.getNeeds().get(i);
					needs[i] = Need.create(need.getQuantity(),
							need.getDescription());
					needs[i].setEncodedKey(need.getEncodedKey());
				}

				SocialProject newProject = SocialProject.create(
						project.getName(), project.getX(), project.getY(),
						needs);
				newProject.setImage1(project.getImage1());
				newProject.setImage2(project.getImage2());
				
				newProject.setDescription(project.getDescription());
				newProject.setEncodedKey(project.getEncodedKey());
				
				newProject.setLocationString(project.getLocationString());

				results.add(newProject);
			}
			return results;
		} finally {
			query.closeAll();
		}
	}

	@Override
	public String testObject() {
		List<SocialProject> project = queryAllProjects();
		return "PCount " + project.size();
	}

	private void testEmpty() {
		List<SocialProject> project = queryAllProjects();
		if (!project.isEmpty())
			return;

		log.info("Creating dummy projects");

		SocialProject s = SocialProject.create("Test project1", 400, 300);
		s.setDescription("Lorem ipsum dolor sit amet, consectetur adipiscing elit.");
		// "Etiam accumsan semper elit semper vestibulum. Nullam commodo ullamcorper gravida. Mauris pellentesque dapibus sem vitae convallis. Ut lacinia varius auctor. Pellentesque et posuere arcu. Sed eget nisi ut est tincidunt interdum ornare ut justo. In enim erat, faucibus at iaculis viverra, gravida vulputate ipsum. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Etiam dictum tempor bibendum. Vestibulum vel nisl justo. Nullam vehicula dictum mauris, vitae bibendum orci vehicula nec. Integer placerat aliquam mollis. Morbi sit amet felis vitae orci vehicula porttitor eu sit amet diam. Ut ullamcorper imperdiet leo, sed convallis sapien auctor sit amet. Proin risus ante, ultrices ut imperdiet a, suscipit vel mauris. Donec pulvinar ultrices quam, id vulputate nulla euismod at. Ut sed vehicula neque. In ultricies viverra porta. Sed in orci justo, eu dapibus urna. Morbi tempus tempor metus at semper. Integer commodo metus tellus. Donec laoreet, lacus eu rutrum suscipit, nulla turpis consequat turpis, quis sollicitudin turpis massa vel nulla. Fusce quis tortor ipsum, a luctus turpis. Nunc nec ultrices nisl. Etiam lorem ligula, suscipit sit amet viverra eu, blandit quis tortor. Donec massa enim, egestas ut porttitor ac, viverra eu turpis.");
		s.setLocationString("Test-Location1");

		SocialProject s2 = SocialProject.create("Test project2", 200, 200, Need
				.create(1, "T-Shirt, XL"), Need.create(400, "Pfannen"), Need
				.create(3, "Handtuecher"), Need.create(5, "T-Shirt,S "));
		s2.setDescription("Lorem ipsum dolor sit amet, consectetur adipiscing elit.");
		// "Etiam accumsan semper elit semper vestibulum. Nullam commodo ullamcorper gravida. Mauris pellentesque dapibus sem vitae convallis. Ut lacinia varius auctor. Pellentesque et posuere arcu. Sed eget nisi ut est tincidunt interdum ornare ut justo. In enim erat, faucibus at iaculis viverra, gravida vulputate ipsum. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Etiam dictum tempor bibendum. Vestibulum vel nisl justo. Nullam vehicula dictum mauris, vitae bibendum orci vehicula nec. Integer placerat aliquam mollis. Morbi sit amet felis vitae orci vehicula porttitor eu sit amet diam. Ut ullamcorper imperdiet leo, sed convallis sapien auctor sit amet. Proin risus ante, ultrices ut imperdiet a, suscipit vel mauris. Donec pulvinar ultrices quam, id vulputate nulla euismod at. Ut sed vehicula neque. In ultricies viverra porta. Sed in orci justo, eu dapibus urna. Morbi tempus tempor metus at semper. Integer commodo metus tellus. Donec laoreet, lacus eu rutrum suscipit, nulla turpis consequat turpis, quis sollicitudin turpis massa vel nulla. Fusce quis tortor ipsum, a luctus turpis. Nunc nec ultrices nisl. Etiam lorem ligula, suscipit sit amet viverra eu, blandit quis tortor. Donec massa enim, egestas ut porttitor ac, viverra eu turpis.");
		s2.setLocationString("Test-Location2");


		Image image1 = loadImage("/org/socialtourist/web/client/images/demo_foto1.jpg");
		Image image2 = loadImage("/org/socialtourist/web/client/images/demo_foto2.jpg");
		
		PersistenceManager pm = PMF.get().getPersistenceManager();

		try {
			pm.makePersistent(image1);
			pm.makePersistent(image2);

			s2.setImage1(image1.getId());
			s2.setImage2(image2.getId());
			
			
			pm.makePersistent(s);
			pm.makePersistent(s2);
			
			
			
		} finally {
			pm.close();
		}

	}

	private Image loadImage (String path)
	{
	Image image = new Image();
	log.info("Trying to load image " + path);
	try {
		image.setImageType("image/jpg");
		InputStream stream = getClass().getResourceAsStream(path);
		ByteArrayOutputStream out = new ByteArrayOutputStream();

		int i = stream.read();
		while (i != -1) {
			out.write(i);
			i = stream.read();
		}

		image.setImage(out.toByteArray());
	} catch (IOException e) {
		image = null;
	}
	return image;
	}
	
	@Override
	public void donateNeeds(List<Need> needs, String email) {
		log.info(String.format("Donating %d needs, mail %s", needs.size(),
				"mario@tokarz.eu"));
		sendConfirmationMail(needs, "mario@tokarz.eu");

	}

	public void sendConfirmationMail(List<Need> needsId, String email) {
		Properties props = new Properties();
		Session session = Session.getDefaultInstance(props, null);

		String msgBody = "TestMessageFromSocialTourist";

		try {
			Message msg = new MimeMessage(session);
			msg.setFrom(new InternetAddress("mario.tokarz@googelmail.com",
					"Mario Tokarz"));
			msg.addRecipient(Message.RecipientType.TO, new InternetAddress(
					email, email));
			msg.addRecipient(Message.RecipientType.CC, new InternetAddress(
					"mario.tokarz@googelmail.com", "Mario Tokarz"));
			msg.setSubject("SocialTourist Example Mail");
			msg.setText(msgBody);
			Transport.send(msg);

		} catch (AddressException e) {
			log.log(Level.SEVERE,
					String.format("Could not send mail message to %s", email),
					e);
			e.printStackTrace();
		} catch (MessagingException e) {
			log.log(Level.SEVERE,
					String.format("Could not send mail message to %s", email),
					e);
			e.printStackTrace();
		} catch (UnsupportedEncodingException e) {
			log.log(Level.SEVERE,
					String.format("Could not send mail message to %s", email),
					e);
			e.printStackTrace();
		}
	}

	@Override
	public String login(String user, String password) throws SocialTouristException 
	{
		if (user != null && user.equals("mario") && password != null && password.equals("to"))
		{
			HttpServletRequest request = this.getThreadLocalRequest();
			HttpSession session = request.getSession();
			
			session.setAttribute(REGISTERED_USER, new User(true));
			
			log.info("Succesfully logged in user " + user);
			
			return session.getId();
		}
		
		log.info("Could not login user " + user);
		throw new SocialTouristException("Username or password do not match.");
	}
	
}
